package genetic.core;

/**
 * This class represents individual in manner of GAs.
 */
public abstract class Individual implements Comparable<Individual>, Cloneable, Variable {

    /**
     * This value represents that fitness should be reevaluated.
     */
	private static final double NON_INITIALIZED = -1.0;
	protected double fitness;
	
	/**
	 * Default constructor.
	 */
	public Individual() {		
		this.fitness = NON_INITIALIZED;
	}

    /**
     * @return fitness of this individual
     */
	public double getFitness() {
		if (fitness == NON_INITIALIZED) {
			fitness = evaluate();
		}
		
		return fitness;
	}

	/**
	 * Evaluate fitness of particular individuals.
	 * 
	 * @return fitness of individual
	 */
	protected abstract double evaluate();
	
	/**
	 * Return true if this individual is ideal. For some problems we may
	 * be not able to detect this.
	 * 
	 * @return whether is this individual ideal, false otherwise
	 */
	public abstract boolean isIdeal();

	@Override
	public int compareTo(Individual other) {
		final double otherFitness = other.getFitness();
		final double thisFitness = this.fitness;
		
		if (thisFitness < otherFitness) {
			return -1;
		} else if (thisFitness == otherFitness) {
			return 0;
		} else {
			return 1;
		}
	}

	/**
	 * Clone of individual sets it's fitness to {@link #NON_INITIALIZED} value - so it
	 * will have to be evaluated when asking for fitness.
	 * 
	 * @return cloned individual
	 */
	public Individual clone() {
		Individual clone = null;
		
		try {
			clone = (Individual) super.clone();
		} catch (CloneNotSupportedException e) {
			e.printStackTrace();
		}
		
		clone.fitness = NON_INITIALIZED;
		
		return clone;
	}
	
	
}
